#ifndef _WEBBOT_IE
#define _WEBBOT_IE

#include <windows.h>
#define INITGUID
#include <initguid.h>
#include <exdisp.h>
#include <memory.h>

#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "mshtml.h"

#include "iwebbot.hpp"


class webbot_ie: public iwebbot
{

public:
	webbot_ie(const char* dispatch_struct_filename);
	void dispatch(void);

protected:

private:
	// private methods 
	bool init_web_browser();
	IDispatch* get_dispatch_interface();
	bool open_URL(); 

	IHTMLDocument2* get_HTML_document_interface(IDispatch* pDisp=NULL);
	IHTMLElementCollection* get_HTML_element_collection(IHTMLDocument2* pHTMLDocument2 =NULL);

	template <class T> bool put_input_template_value(std::string const& _str, T* pInputElement =NULL);
	template <class T> bool on_input_template_hidden(T* pInputHiddenElement, std::string const& _encryption_config, 
		dispatch_struct::encryption_task& _encryption_tsk);

	bool on_input_hidden(std::string const &_strName, std::string const &_strValue, dispatch_struct::encryption_task& _task, 
		IHTMLElementCollection* pIHTMLElementCollection = NULL);
	bool on_input_password(std::string const &_strName, std::string const& _encryption_config, dispatch_struct::encryption_task& _encryption_tsk, 
		IHTMLElementCollection* pIHTMLElementCollection = NULL);
	

	bool on_input_text(std::string const &_strName, std::string const &_strValue, IHTMLElementCollection* pIHTMLElementCollection=NULL);
	void on_input_image(const std::string& _bttnName, IHTMLElementCollection* pIHTMLElementCollection=NULL);
	void on_input_button(const std::string& _bttnName, IHTMLElementCollection* pIHTMLElementCollection=NULL);
	void on_form_action(const std::string& _formName, IHTMLElementCollection* pIHTMLElementCollection =NULL);
	void on_jscript_action(const std::string& _formName);

	IHTMLInputElement* get_HTML_input_element(const IID _IID_IHTMLInputElement, long& _i, 
			long const& _celem, IHTMLElementCollection* pColl, IHTMLElement** _pElem);

	template <class T> T* get_HTML_input_template_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem, const IID _IID_IHTMLInputElement);
	IHTMLInputButtonElement* get_HTML_input_button_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);
	IHTMLInputTextElement* get_HTML_input_text_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);
	IHTMLInputImage* get_HTML_input_image(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);
	IHTMLInputHiddenElement* get_HTML_input_hidden_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);
	IHTMLFormElement* get_HTML_form_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);
	IHTMLInputButtonElement* get_HTML_button_element(std::string const& _name, IHTMLElementCollection* pColl, IHTMLElement** _pElem);

	// get element methods: by Id, by tag_name, by outer HTML
	IHTMLElement* get_element_byID(std::string const& _szId, IHTMLElementCollection *pColl);
	IHTMLElement* get_element_by_outer_HTML(std::string const& _szOuterHTML, IHTMLElementCollection *pColl);
	IHTMLElement* get_element_by_name(std::string const& _szOuterHTML, IHTMLElementCollection *pColl);

	bool submit(IHTMLFormElement* pForm = NULL);
	bool submit(IHTMLInputImage* pImageButton = NULL);

	void wait_ready_state();
	bool wait_ready_state_interactive();

	void dispose();

	void perform_input_actions(IHTMLElementCollection* pIHTMLElementCollection);
	bool set_visible(bool const& _isVisible =false);	

	bool get_post_data(LPVARIANT pvPostData); // pack posting data into a SAFEARRAY of BYTEs. Return in a VARIANT
	std::string const decrypt_token(std::string const& _encryption_config);
	std::string const get_url_encode();

	void jscript(std::string const& _script, IHTMLDocument2*   pDocument);
	
	// private data
	IWebBrowser2* webbrowser;
};

#endif